package com.ConfigServer.service;

import java.io.FileNotFoundException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.cloud.config.environment.Environment;
import org.springframework.cloud.config.environment.PropertySource;
import org.springframework.context.EnvironmentAware;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;

import com.ConfigServer.entity.NameValuePair;
import com.ConfigServer.entity.PropertyEntity;
import com.ConfigServer.mapper.ConfigInfoMapper;

@Service
public class ConfigRepositoryService implements EnvironmentAware{
	private org.springframework.core.env.Environment env;
	
	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	@Autowired
	private ConfigInfoMapper configInfoMapper;
	
	//也可以采用如下方式注入Environment，而不用实现EnvironmentAware
//	@Autowired
//	private ConfigurableEnvironment env;
	
	@Override
	public void setEnvironment(org.springframework.core.env.Environment environment) {
		env = environment;
	}
	
	public Environment getEnvironmentFromProperties(String application, String profile, String label){
		//如果属性个数很少且名字确定，也可以用@Value的方式注入
		RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(env,application+".");
		Map<String, Object> propertyMap = propertyResolver.getSubProperties(null);
		PropertySource propertySource = new PropertySource("configServer", propertyMap);
		Environment environment = new Environment(application, profile, label, "1.0", null);
		environment.add(propertySource);
		return environment;
	}

	//直接使用JdbcTemplate来访问数据库
	public Environment getEnvironmentFromDatabase(String application, String profile, String label) {
		ResultSetExtractor<List<NameValuePair>> rse = new ResultSetExtractor<List<NameValuePair>>() {
			@Override
			public List<NameValuePair> extractData(ResultSet rs) throws SQLException, DataAccessException {
				List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
				while (rs.next()) {
					NameValuePair nameValuePair = new NameValuePair();
					nameValuePair.setName(rs.getString("key"));
					nameValuePair.setValue(rs.getString("value"));
					nameValuePairs.add(nameValuePair);
				}
				return nameValuePairs;
			}
		};
		String sql = "select key , value from config_info where application=?";
		Object[] params = new Object[1];
		params[0] = application;
		List<NameValuePair> nameValuePairs = jdbcTemplate.query(sql, params, rse);
		if(nameValuePairs == null || nameValuePairs.size() == 0)
			return null;
		Map<String, Object> propertyMap = new HashMap<String, Object>();
		for(NameValuePair nameValuePair:nameValuePairs) {
			propertyMap.put(nameValuePair.getName(), nameValuePair.getValue());
		}
		PropertySource propertySource = new PropertySource("configServer", propertyMap);
		Environment environment = new Environment(application, profile, label, "1.0", null);
		environment.add(propertySource);
		return environment;
	}
	
	//使用Mybatis来访问数据库
	public Environment getEnvironmentFromDatabaseByMybatis(String application, String profile, String label) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("application", application);
		List<NameValuePair> nameValuePairs = configInfoMapper.getConfigInfo(params);
		if(nameValuePairs == null || nameValuePairs.size() == 0)
			return null;
		Map<String, Object> propertyMap = new HashMap<String, Object>();
		for(NameValuePair nameValuePair:nameValuePairs) {
			propertyMap.put(nameValuePair.getName(), nameValuePair.getValue());
		}
		PropertySource propertySource = new PropertySource("configServer", propertyMap);
		Environment environment = new Environment(application, profile, label, "1.0", null);
		environment.add(propertySource);
		return environment;
	}
	
	public PropertyEntity getProperties(String application,String profile,String label) {
		//TODO
		return null;
	}
	
	//测试事务控制
	@Transactional(propagation=Propagation.REQUIRED,readOnly=false,rollbackFor=Exception.class,
			noRollbackFor=FileNotFoundException.class)
	public void testTransactional(String value) {
		configInfoMapper.updateProperty1(value);
		configInfoMapper.updateProperty1Error(value);
	}
	
}
